#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include "main.h"
#include "Liot_AT.h"

extern Liot_AT_tcp_status_t g_tcp_status[SOCKET_ID_NUM];

uint8_t g_at_rsp[AT_RSP_SIZE] = {0};
uint8_t AT_rsp_status = 0;


uint8_t g_AT_CMEE_status = AT_CMEE_DISABLE;

void Liot_AT_cmd_rsp_callback(uint8_t *data, uint16_t len)
{
    uint8_t *offset = NULL;
    strcpy(g_at_rsp, data);
    AT_rsp_status = 1;
    AT_LOGI("ATrsp: %s", data);

    if(Liot_check_socket_status() != 0)
    {
        if(Liot_AT_rsp_check_keyword(g_at_rsp, "+LIPURC") == AT_OK)
        {
            uint8_t param_num = 0;
            uint32_t socket_id = 0;
            uint32_t type = 0;
            uint32_t type_data = 0;
            uint8_t rbuf[1024] = {0};

            param_num = Liot_AT_rsp_get_param_num(g_at_rsp, "+LIPURC");
            if(param_num == 3)
            {
                Liot_AT_rsp_get_param(g_at_rsp, "+LIPURC", 0, AT_PARAM_TYPE_DEC, &socket_id);
                Liot_AT_rsp_get_param(g_at_rsp, "+LIPURC", 1, AT_PARAM_TYPE_DEC, &type);
                Liot_AT_rsp_get_param(g_at_rsp, "+LIPURC", 2, AT_PARAM_TYPE_DEC, &type_data);
                if(type == 0)
                {
                    Liot_AT_socket_callback(socket_id, AT_SOCKET_URC_RECV_ERROR, NULL, &type_data);
                }
                else
                {
                    Liot_AT_socket_callback(socket_id, AT_SOCKET_URC_RECV_DATA, NULL, &type_data);
                }
            }
            else if(param_num == 4)
            {
                Liot_AT_rsp_get_param(g_at_rsp, "+LIPURC", 0, AT_PARAM_TYPE_DEC, &socket_id);
                Liot_AT_rsp_get_param(g_at_rsp, "+LIPURC", 1, AT_PARAM_TYPE_DEC, &type);
                Liot_AT_rsp_get_param(g_at_rsp, "+LIPURC", 2, AT_PARAM_TYPE_DEC, &type_data);
                Liot_AT_rsp_get_param(g_at_rsp, "+LIPURC", 3, AT_PARAM_TYPE_STR, rbuf);
                if(type == 0)
                {
                    Liot_AT_socket_callback(socket_id, AT_SOCKET_URC_RECV_ERROR, NULL, &type_data);
                }
                else
                {
                    Liot_AT_socket_callback(socket_id, AT_SOCKET_URC_RECV_DATA, rbuf, &type_data);
                }
            }
        }
    }
    else if(Liot_check_mqtt_status() != 0)
    {
        if(Liot_AT_rsp_check_keyword(g_at_rsp, "+LMQTTURC") == AT_OK)
        {
            uint8_t state_str[8] = {0};
            uint32_t id = 0;
            uint32_t msgid = 0;
            uint8_t rbuf[1024] = {0};
            uint8_t topic[256] = {0};
            Liot_AT_rsp_get_param(g_at_rsp, "+LMQTTURC", 0, AT_PARAM_TYPE_STR, state_str);
            if(state_str[0] == 'S')
            {
                Liot_AT_rsp_get_param(g_at_rsp, "+LMQTTURC", 1, AT_PARAM_TYPE_DEC, &id);
                Liot_AT_rsp_get_param(g_at_rsp, "+LMQTTURC", 2, AT_PARAM_TYPE_DEC, &msgid);
                Liot_AT_mqtt_callback(AT_MQTT_URC_STATS, id, msgid, NULL, NULL, 0);
            }
            else if(state_str[0] == 'R')
            {
                Liot_AT_rsp_get_param(g_at_rsp, "+LMQTTURC", 1, AT_PARAM_TYPE_DEC, &id);
                Liot_AT_rsp_get_param(g_at_rsp, "+LMQTTURC", 2, AT_PARAM_TYPE_DEC, &msgid);
                Liot_AT_rsp_get_param(g_at_rsp, "+LMQTTURC", 3, AT_PARAM_TYPE_STR, topic);
                Liot_AT_rsp_get_param(g_at_rsp, "+LMQTTURC", 4, AT_PARAM_TYPE_STR, rbuf);
                Liot_AT_mqtt_callback(AT_MQTT_URC_RECV, id, msgid, topic, rbuf, strlen(rbuf));
            }
        }
    }
}

void Liot_AT_get_rsp_error_reason(uint8_t *rsp)
{
    uint8_t *cmee_offset = NULL;
    switch(g_AT_CMEE_status)
    {
        case AT_CMEE_DISABLE:
        {
            AT_LOGE("AT ERROR\r\n");
            break;
        }
        case AT_CMEE_BYTE:
        {
            cmee_offset = strstr(rsp, ":");
            AT_LOGE("AT ERROR%s\r\n", cmee_offset);
            break;
        }
        case AT_CMEE_STRING:
        {
            cmee_offset = strstr(rsp, ":");
            AT_LOGE("AT ERROR%s\r\n", cmee_offset);
            break;
        }
        default:break;
    }
}

AT_errorcode_t Liot_get_product_info(Liot_product_info_t *info)
{

}

AT_errorcode_t Liot_get_imei(uint8_t *imei)
{
    char cmd[] = "AT+LGSN=2\r\n";
    uint16_t rsplen = 0;
    uint8_t *offset = NULL;
    uint8_t *buf = NULL;

    if(imei == NULL)
    {
        return AT_INVALID_PARAM;
    }
    Liot_AT_cmd_send(cmd, strlen(cmd));
    if(Liot_AT_wait_rsp(25000) != AT_OK)
    {
        return AT_TIMEOUT;
    }
    if(strstr(g_at_rsp, "ERROR") != NULL)
    {
        Liot_AT_get_rsp_error_reason(g_at_rsp);
        return AT_RECV_ERROR;
    }
    Liot_AT_rsp_get_param(g_at_rsp, "+LGSN", 0, AT_PARAM_TYPE_STR, imei);

    return AT_OK;
}

AT_errorcode_t Liot_set_cfun(uint8_t cfun)
{
    char cmd[16] = "";
    if(cfun != 0 && cfun != 1 && cfun != 4)
    {
        return AT_INVALID_PARAM;
    }
    sprintf(cmd, "AT+CFUN=%d\r\n", cfun);
    Liot_AT_cmd_send(cmd, strlen(cmd));
    if(Liot_AT_wait_rsp(25000) != AT_OK)
    {
        return AT_TIMEOUT;
    }
    if(strstr(g_at_rsp, "ERROR") != NULL)
    {
        Liot_AT_get_rsp_error_reason(g_at_rsp);
        return AT_RECV_ERROR;
    }
    return AT_OK;
}

AT_errorcode_t Liot_set_CMEE(Liot_AT_CMEE_type_t type)
{
    char cmd[16] = "";
    if(type > AT_CMEE_MAX || type < AT_CMEE_DISABLE)
    {
        return AT_INVALID_PARAM;
    }
    sprintf(cmd, "AT+CMEE=%d\r\n", type);
    Liot_AT_cmd_send(cmd, strlen(cmd));
    if(Liot_AT_wait_rsp(5000) != AT_OK)
    {
        return AT_TIMEOUT;
    }
    if(strstr(g_at_rsp, "ERROR") != NULL)
    {
        Liot_AT_get_rsp_error_reason(g_at_rsp);
        return AT_RECV_ERROR;
    }
    switch(type)
    {
        case AT_CMEE_DISABLE:
        {
            g_AT_CMEE_status = AT_CMEE_DISABLE;
            break;
        }
        case AT_CMEE_BYTE:
        {
            g_AT_CMEE_status = AT_CMEE_BYTE;
            break;
        }
        case AT_CMEE_STRING:
        {
            g_AT_CMEE_status = AT_CMEE_STRING;
            break;
        }
        default:break;
    }
    return AT_OK;
}

AT_errorcode_t Liot_get_CMEE(void)
{
    char cmd[] = "AT+CMEE?\r\n";
    uint8_t *cmee_offset = NULL;
    uint8_t cmee_status = 0;

    Liot_AT_cmd_send(cmd, strlen(cmd));
    if(Liot_AT_wait_rsp(5000) != AT_OK)
    {
        return AT_TIMEOUT;
    }
    if(strstr(g_at_rsp, "ERROR") != NULL)
    {
        Liot_AT_get_rsp_error_reason(g_at_rsp);
        return AT_RECV_ERROR;
    }
    cmee_offset = strstr(g_at_rsp, ":");
//    sscanf(&cmee_offset[2], "%d", &cmee_status);
    Liot_AT_rsp_get_param(g_at_rsp, "+CMEE", 0, AT_PARAM_TYPE_DEC, &cmee_status);
    g_AT_CMEE_status = cmee_status;
    return AT_OK;
}

AT_errorcode_t Liot_get_iccid(uint8_t *iccid)
{
    char cmd[] = "AT+LCCID\r\n";
    uint8_t *offset = NULL;

    if(iccid == NULL)
    {
        return AT_INVALID_PARAM;
    }
    Liot_AT_cmd_send(cmd, strlen(cmd));
    if(Liot_AT_wait_rsp(5000) != AT_OK)
    {
        return AT_TIMEOUT;
    }
    if(strstr(g_at_rsp, "ERROR") != NULL)
    {
        Liot_AT_get_rsp_error_reason(g_at_rsp);
        return AT_RECV_ERROR;
    }
    offset = strstr(g_at_rsp, ":");
    memcpy(iccid, &offset[2], 20);
    return AT_OK;
}

AT_errorcode_t Liot_get_cereg(uint8_t *cereg)
{
    uint8_t cmd[] = "AT+CEREG?";
    uint8_t *offset = NULL;
    uint8_t n = 0;
    uint8_t stat = 0;

    if(cereg == NULL)
    {
        return AT_INVALID_PARAM;
    }
    Liot_AT_cmd_send(cmd, strlen(cmd));
    if(Liot_AT_wait_rsp(5000) != AT_OK)
    {
        return AT_TIMEOUT;
    }
    if(strstr(g_at_rsp, "ERROR") != NULL)
    {
        Liot_AT_get_rsp_error_reason(g_at_rsp);
        return AT_RECV_ERROR;
    }
//    offset = strstr(g_at_rsp, ":");
//    sscanf(&offset[2], "%d,%d", &n, &stat);
    Liot_AT_rsp_get_param(g_at_rsp, "+CEREG", 0, AT_PARAM_TYPE_DEC, &n);
    Liot_AT_rsp_get_param(g_at_rsp, "+CEREG", 1, AT_PARAM_TYPE_DEC, &stat);

    *cereg = stat;

    return AT_OK;
}

AT_errorcode_t Liot_AT_module_reset(void)
{
    uint8_t cmd[] = "AT+LRST\r\n";

    Liot_AT_cmd_send(cmd, strlen(cmd));
    if(Liot_AT_wait_rsp(5000) != AT_OK)
    {
        return AT_TIMEOUT;
    }
    if(strstr(g_at_rsp, "ERROR") != NULL)
    {
        Liot_AT_get_rsp_error_reason(g_at_rsp);
        return AT_RECV_ERROR;
    }

    AT_delay_ms(2000);
    AT_LOGI("Module Reset OK!\r\n");
    return AT_OK;
}

